package castle.defense.project;

import java.util.Random;

import android.graphics.Canvas;
import android.graphics.Color;

/**
 * The class defining an enemy NPC. The main purpose of the enemy
 * is to attack the player's castle; thus the player must try to destroy
 * the enemies. Enemies have health points, an associated point value for
 * their defeat, and a weapon.  Additionally, an enemy may carry credits
 * that are dropped upon their death. In the game, the enemies advance toward
 * the player's castle and ultimately attack according to the range of their 
 * carried weapon.
 * 
 * @author KevinJoslyn
 *
 */
public class Enemy extends Moveable {
	
	public static final int enemy1 = 1500, enemy2 = 1501, juggernaut = 1502;
	private static final int height = 49;
	public int baseHealth;
	public int healthPoints;
	public int pointValue;
	public Weapon weapon;
	
	/**
	 * Basic Enemy constructor with predefined LinearPoint
	 * 
	 * @param image			The hash key of this enemy's image.
	 * @param p				The LinearPoint representing the enemy's movement in the game
	 * @param size			The size of this enemy
	 * @param deathSound	The hash key of this enemy's death sound.
	 * 
	 * @param bh 		The enemy's base health
	 * @param pv		The enemy's point value (the amount of points the 
	 * 					player is awarded for defeating this enemy.)
	 * @param w			The weapon carried by the enemy
	 */
	public Enemy(int image, LinearPoint p, float size, int deathSound, int bh, int pv, Weapon w) {
		
		super(height, image, p, size, deathSound);
		baseHealth = bh;
		healthPoints = bh;
		pointValue = pv;
		weapon = w;
	}
	
	/**
	 * Enemy constructor without predefined LinearPoint
	 * 
	 * @param image		The hash key of this object's image.
	 * @param x			The enemy's x coordinate (abstract units)
	 * @param y			The enemy's y coordinate (abstract units)
	 * @param speed		The enemy's speed
	 * @param angle		The angle representing the enemy's direction of travel
	 * @param size		The size of this enemy
	 * @param deathSound	The hash key of this enemy's death sound.
	 * 
	 * @param bh 		The enemy's base health
	 * @param pv		The enemy's point value (the amount of points the 
	 * 					player is awarded for defeating this enemy.)
	 * @param cc		The amount of credits carried by the enemy
	 * @param w			The weapon carried by the enemy
	 */
	public Enemy(int image, double x, double y, double speed, double angle,
			float size, int deathSound, int bh, int pv, Weapon w) {
		
		this(image, new LinearPoint(x,y,speed,angle), size, deathSound, bh, pv, w);
	}
	
	public Enemy(LinearPoint p, float size, int bh, int pv, Weapon w) {
		this(-1,p,size,-1,bh,pv,w);
	}
	
	public Enemy(double x, double y, double speed, double angle, float size, int bh, int pv, Weapon w) {
		this(new LinearPoint(x,y,speed,angle), size, bh, pv, w);
	}
	
	public Enemy(double x, double y, double speed, double angle, float size, int bh, int pv, Weapon w, int image) {
		this(image,new LinearPoint(x,y,speed,angle), size, -1, bh, pv, w);
	}
	
	public Enemy(double x, double y, float size, int bh, int pv) {
		this(new LinearPoint(x,y,0,0), size, bh, pv, null);
	}
	
	/**
	 * Subtracts hit points from the enemy. 
	 * 
	 * @param amt		The amount of damage to be taken
	 */
	public void takeDamage(int amt) {
		healthPoints -= amt;
	}
	
	/**
	 * Asks whether the given Enemy object should be destroyed and thereby
	 * removed from the screen.
	 * 
	 * @return True if the enemy's health points are at or below 0
	 * 		   False if the enemy is not yet dead (health points >= 0)
	 */
	public boolean destroy() {
		
		if(healthPoints <= 0) {
			onDeath();
			return true;
		}
		return false;
	}
	
	/** To be called when an enemy dies. Upon death, the player's 
	 * point total, kill streak, and number of enemies killed will be increased.
	 * The enemy's death sound should also be played.
	 * 
	 * @see Player
	 * @see Moveable.makeDeathSound()
	 */
	public void onDeath() {
		makeDeathSound();
	}

	public void draw(Canvas c) {
		GraphicsEngine.drawHealthBar(c, p.x-size, p.y+size, p.x+size, p.y+size+PE.screenPercentY(0.5), healthPoints, baseHealth);
		if(image>=0) {
			GraphicsEngine.draw(c, image, p.x-size, p.y+size);
		} else {
			GraphicsEngine.drawOval(c, p, size, Color.MAGENTA);
		}
	}

	public int height() {
		return height;
	}
	
	public int getPointValue() {return pointValue;}
	
	
	public Projectile updateE(long milli) {
		weapon.update(milli);
		if(weapon.inRange(p.y)) {
			if(weapon.canAttack()) {
				//just shoot straight down
				return weapon.attack(p.x, p.y, p.x, p.y-1);
			}
		} else {
			super.update(milli);
		}
		return null;
	}
	
	/**
	 * @param time	Time at which enemy enters the screen.
	 * @return
	 */
	
	public static Enemy RangedEnemy1(double time, long seed) {
		Enemy e;
		Random r = new Random(seed);
		
		double speed = getSpeed(10); //Percent of screen in Y traveled per second
		double size = getSize(2); //Percent of screen covered in Y (in radius)
		
		double x = PE.screenPercentX(r.nextDouble()*90.0 + 5.0); //[5.0,95.0]
		double y = speed * time + PE.sizeY; // D = R*T
		int health = 15;
		int pts = 75;
		Weapon weapon = Weapon.createEnemyGun();
		
		e = new Enemy(x, y, speed, -Math.PI/2, (float)size, health, pts, weapon, Enemy.enemy1);
		
		return e;
	}
	
	public static Enemy MeleeEnemy1(double time, long seed) {
		Enemy e;
		Random r = new Random(seed);
		
		double speed = getSpeed(15); //Percent of screen in Y traveled per second
		double size = getSize(2.5); //Percent of screen covered in Y (in radius)
		
		double x = PE.screenPercentX(r.nextDouble()*90.0 + 5.0); //[5.0,95.0]
		double y = speed * time + PE.sizeY; // D = R*T
		int health = 25;
		int pts = 50;
		Weapon weapon = Weapon.createMelee(2.5, 10, 1.25);
		
		e = new Enemy(x, y, speed, -Math.PI/2, (float)size, health, pts, weapon, Enemy.enemy2);
		
		return e;
	}
	
	public static Enemy Juggernaut(double time, long seed, int wave) {
		Enemy e;
		Random r = new Random(seed);
		
		double speed = getSpeed(7.5); //Percent of screen in Y traveled per second
		double size = getSize(6); //Percent of screen covered in Y (in radius)
		
		double x = PE.screenPercentX(r.nextDouble()*90.0 + 5.0); //[5.0,95.0]
		double y = speed * time + PE.sizeY; // D = R*T
		int health = 150 + wave*10;
		int pts = 250;
		Weapon weapon = Weapon.createMelee(6, 50, 2.0);
		
		e = new Enemy(x, y, speed, -Math.PI/2, (float)size, health, pts, weapon, Enemy.juggernaut);
		
		return e;
	}
	
	public static double getSpeed(double setSpeed) {
		return PE.screenPercentY(setSpeed);
	}
	
	public static double getSize(double percent) {
		return PE.screenPercentY(percent);
	}
}
